package cc.autoapi.pucong.auto.flow.core.root.utils;

import cc.autoapi.pucong.auto.flow.core.root.exception.AutoFlowException;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class FileUtil {

    /**
     * 附件上传
     *
     * @param file
     */
    public static Boolean uploadFile(MultipartFile file, String uploadPath) {
        if (file.isEmpty()) {
            throw new AutoFlowException("附件为空");
        }
        File uploadFile = new File(uploadPath);
        if (!uploadFile.getParentFile().getParentFile().exists()) {
            uploadFile.getParentFile().getParentFile().mkdirs();
        }
        if (!uploadFile.getParentFile().exists()) {
            uploadFile.getParentFile().mkdirs();
        }
        try {
            if (!uploadFile.exists()) {
                uploadFile.createNewFile();
            }
            file.transferTo(uploadFile);
        } catch (IOException e) {
            log.error("上传附件失败", e);
            throw new AutoFlowException("上传失败");
        }
        return true;
    }

    /**
     * 删除文件
     *
     * @param path
     * @return
     */
    public static Boolean deleteFile(String path) {
        File file = new File(path);
        // 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
        if (file.exists() && file.isFile()) {
            if (file.delete()) {
                log.info("删除单个文件" + path + "成功！");
                return true;
            } else {
                log.error("删除单个文件" + path + "失败！");
                return false;
            }
        } else {
            log.error("删除单个文件失败：" + path + "不存在！");
            return false;
        }
    }

    public static void downLoadFile(String path, String fileName, HttpServletResponse response) {
        if (StringUtils.isBlank(path)) {
            throw new AutoFlowException("传入参数错误");
        }
        File file = new File(path);
        //当文件存在
        if (file.exists()) {
            response.reset();
            //首先设置响应的内容格式是force-download，那么你一旦点击下载按钮就会自动下载文件了
            response.setContentType("application/force-download");
            //通过设置头信息给文件命名，也即是，在前端，文件流被接受完还原成原文件的时候会以你传递的文件名来命名
            try {
                // 设置文件名 支持中文 采用中文文件名需要在此处转码
                fileName = new String(fileName.getBytes("GBK"), "ISO_8859_1");
                response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            } catch (UnsupportedEncodingException e) {
                log.error("不支持文件返回设置编码", e);
            }
            //进行读写操作
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                //从源文件中读
                int i = bis.read(buffer);
                while (i != -1) {
                    //写到response的输出流中
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (IOException e) {
                log.error("文件流io异常", e);
            } finally {
                //善后工作，关闭各种流
                try {
                    if (bis != null) {
                        bis.close();
                    }
                    if (fis != null) {
                        fis.close();
                    }
                } catch (IOException e) {
                    log.error("文件流io异常", e);
                }
            }
        } else {
            throw new AutoFlowException("附件下载失败");
        }
    }

    /**
     * 删除文件或者文件夹
     *
     * @param file
     * @return
     */
    public static boolean delFile(File file) {
        if (!file.exists()) {
            return false;
        }

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                delFile(f);
            }
        }
        return file.delete();
    }

    public static boolean delFile(String path) {
        return delFile(new File(path));
    }


    /**
     * 预览图片
     *
     * @param path
     * @param response
     */
    public static void lookFile(String path, String fileName, HttpServletResponse response) {
        if (StringUtils.isBlank(path)) {
            throw new AutoFlowException("传入参数错误");
        }
        File file = new File(path);
        //当文件存在
        if (file.exists()) {
            //进行读写操作
            FileInputStream fis = null;
            ServletOutputStream out = null;
            try {
                fis = new FileInputStream(file);
                out = response.getOutputStream();
                byte[] content = new byte[1024];
                int length = -1;
                while ((length = fis.read(content)) != -1) {
                    out.write(content, 0, length);
                    out.flush();
                }
            } catch (IOException e) {
                log.error("文件流io异常", e);
            } finally {
                //善后工作，关闭各种流
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (fis != null) {
                        fis.close();
                    }
                } catch (IOException e) {
                    log.error("文件流io异常", e);
                }
            }
        } else {
            throw new AutoFlowException("预览图片失败");
        }
    }

    public static void writeToFile(String filePath, JSONObject jo) {
        File file = new File(filePath);
        if (!file.exists()) {
            File parent = file.getParentFile();
            if (!parent.exists()) {
                parent.mkdirs();
            }
        }
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            file.createNewFile();
            // 使用 try-with-resources 语句确保资源在使用后自动关闭
            writer.write(jo.toJSONString(JSONWriter.Feature.PrettyFormat));
        } catch (IOException e) {
            log.error("写入文件失败", e);
            throw new AutoFlowException("写入文件失败");
        }
    }

    public static String readFileContent(String path) {
        String jsonStr = null;
        try (
                Reader reader = new InputStreamReader(new FileInputStream(path), "Utf-8");
        ) {
            int ch = 0;
            StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            jsonStr = sb.toString();
        } catch (Exception e) {
            log.error("读取配置文件失败", e);
            throw new AutoFlowException("读取配置文件失败");
        }
        return jsonStr;
    }

    public static MultipartFile getMultipartFile(String fileName, String contentType, byte[] bytes) {
        return new MultipartFile() {
            @Override
            public String getName() {
                //直接使用了原文件的属性
                return fileName;
            }

            @Override
            public String getOriginalFilename() {
                //直接使用了原文件的属性
                return fileName;
            }

            @Override
            public String getContentType() {
                //直接使用了原文件的属性
                return contentType;
            }

            @Override
            public boolean isEmpty() {
                return bytes.length == 0;
            }

            @Override
            public long getSize() {
                return bytes.length;
            }

            @Override
            public byte[] getBytes() {
                return bytes;
            }

            @Override
            public InputStream getInputStream() {
                return new ByteArrayInputStream(bytes);
            }

            @Override
            public void transferTo(File file) throws IOException, IllegalStateException {
                new FileOutputStream(file).write(bytes);
            }

            @Override
            public String toString() {
                return super.toString();
            }
        };
    }

    public static List<File> getChildrenFileList(File file) {
        List<File> files = new ArrayList<>();
        File[] fs = file.listFiles();
        for (File f : fs) {
            if (f.isDirectory()) {
                //若是目录，则递归打印该目录下的文件
                files.addAll(getChildrenFileList(f));
            }
            if (f.isFile()) {

                //若是文件，直接打印
                files.add(f);
            }
        }
        return files;
    }
}
